﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DAWSharp.DSP.EQ
{
    public class HighShelf : EQ
    {
        /// <summary>
        ///  Sets initial values for BiQuad High Shelf according to http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
        /// </summary>
        /// <param name="cf">Center Frequency</param>
        /// <param name="q">Q Factor</param>
        /// <param name="dBGain">Gain in Decibels</param>
        /// <param name="sampleFrequency">Sample Frequency</param>
        public HighShelf(float cf, float q, float dBGain, float sampleFrequency)
        {
            w0 = 2.0f * Math.PI * (cf / sampleFrequency);
            sinw0 = Math.Sin(w0);
            cosw0 = Math.Cos(w0);
            A = Math.Pow(10.0f, (dBGain / 40.0f));
            alpha = sinw0 / 2.0f * Math.Sqrt((A + 1 / A) * (1 / q - 1) + 2);

            b0 = A * ((A + 1) + (A - 1) * cosw0 + 2 * Math.Sqrt(A) * alpha);
            b1 = -2 * A * ((A - 1) + (A + 1) * cosw0);
            b2 = A * ((A + 1) + (A - 1) * cosw0 - 2 * Math.Sqrt(A) * alpha);
            a0 = (A + 1) - (A - 1) * cosw0 + 2 * Math.Sqrt(A) * alpha;
            a1 = 2 * ((A - 1) - (A + 1) * cosw0);
            a2 = (A + 1) - (A - 1) * cosw0 - 2 * Math.Sqrt(A) * alpha;

            b0a0 = b0 / a0;
            b1a0 = b1 / a0;
            b2a0 = b2 / a0;
            a1a0 = a1 / a0;
            a2a0 = a2 / a0;
        }

        /// <summary>
        /// Updates values for BiQuad High Shelf according to http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
        /// </summary>
        /// <param name="cf">Center Frequency</param>
        /// <param name="q">Q Factor</param>
        /// <param name="dBGain">Gain in Decibels</param>
        /// <param name="sampleFrequency">Sample Frequency</param>
        public void UpdateValues(float cf, float q, float dBGain, float sampleFrequency)
        {
            w0 = 2.0f * Math.PI * (cf / sampleFrequency);
            sinw0 = Math.Sin(w0);
            cosw0 = Math.Cos(w0);
            A = Math.Pow(10.0f, (dBGain / 40.0f));
            alpha = sinw0 / 2.0f * Math.Sqrt((A + 1 / A) * (1 / q - 1) + 2);

            b0 = A * ((A + 1) + (A - 1) * cosw0 + 2 * Math.Sqrt(A) * alpha);
            b1 = -2 * A * ((A - 1) + (A + 1) * cosw0);
            b2 = A * ((A + 1) + (A - 1) * cosw0 - 2 * Math.Sqrt(A) * alpha);
            a0 = (A + 1) - (A - 1) * cosw0 + 2 * Math.Sqrt(A) * alpha;
            a1 = 2 * ((A - 1) - (A + 1) * cosw0);
            a2 = (A + 1) - (A - 1) * cosw0 - 2 * Math.Sqrt(A) * alpha;

            b0a0 = b0 / a0;
            b1a0 = b1 / a0;
            b2a0 = b2 / a0;
            a1a0 = a1 / a0;
            a2a0 = a2 / a0;
        }
    }
}
